{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Batch Serving Design Pattern\n",
    "\n",
    "This notebook demonstrates the Batch Serving design pattern using BigQuery\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Simple text classification model\n",
    "\n",
    "Let's use the same model that was used in [serving_function.ipynb](serving_function.ipynb) -- a text classification model based on IMDB reviews trained, and exported."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "export/probs/\n",
      "export/probs/sentiment_20200505_232617\n",
      "export/probs/sentiment_20200505_232617/variables\n",
      "export/probs/sentiment_20200505_232617/variables/variables.data-00000-of-00001\n",
      "export/probs/sentiment_20200505_232617/variables/variables.index\n",
      "export/probs/sentiment_20200505_232617/assets\n",
      "export/probs/sentiment_20200505_232617/assets/tokens.txt\n",
      "export/probs/sentiment_20200505_232617/saved_model.pb\n"
     ]
    }
   ],
   "source": [
    "!find export/probs/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gs://ai-analytics-solutions-kfpdemo/mlpatterns/batchserving/saved_model.pb\n",
      "gs://ai-analytics-solutions-kfpdemo/mlpatterns/batchserving/assets/\n",
      "gs://ai-analytics-solutions-kfpdemo/mlpatterns/batchserving/variables/\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Removing gs://ai-analytics-solutions-kfpdemo/mlpatterns/batchserving/assets/tokens.txt#1588793354410693...\n",
      "Removing gs://ai-analytics-solutions-kfpdemo/mlpatterns/batchserving/saved_model.pb#1588793353859489...\n",
      "Removing gs://ai-analytics-solutions-kfpdemo/mlpatterns/batchserving/variables/variables.data-00000-of-00001#1588793354212839...\n",
      "Removing gs://ai-analytics-solutions-kfpdemo/mlpatterns/batchserving/variables/variables.index#1588793354293034...\n",
      "/ [4 objects]                                                                   \n",
      "Operation completed over 4 objects.                                              \n",
      "Copying file://export/probs/sentiment_20200505_232617/saved_model.pb [Content-Type=application/octet-stream]...\n",
      "Copying file://export/probs/sentiment_20200505_232617/variables/variables.data-00000-of-00001 [Content-Type=application/octet-stream]...\n",
      "Copying file://export/probs/sentiment_20200505_232617/variables/variables.index [Content-Type=application/octet-stream]...\n",
      "Copying file://export/probs/sentiment_20200505_232617/assets/tokens.txt [Content-Type=text/plain]...\n",
      "/ [4 files][  4.7 MiB/  4.7 MiB]                                                \n",
      "Operation completed over 4 objects/4.7 MiB.                                      \n"
     ]
    }
   ],
   "source": [
    "%%bash\n",
    "LOCAL_DIR=$(find export/probs | head -2 | tail -1)\n",
    "BUCKET=ai-analytics-solutions-kfpdemo\n",
    "gsutil rm -rf gs://${BUCKET}/mlpatterns/batchserving\n",
    "gsutil cp -r $LOCAL_DIR gs://${BUCKET}/mlpatterns/batchserving\n",
    "gsutil ls gs://${BUCKET}/mlpatterns/batchserving"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load model into BigQuery for batch serving "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "Empty DataFrame\n",
       "Columns: []\n",
       "Index: []"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%bigquery\n",
    "CREATE OR REPLACE MODEL mlpatterns.imdb_sentiment\n",
    "OPTIONS(model_type='tensorflow', model_path='gs://ai-analytics-solutions-kfpdemo/mlpatterns/batchserving/*')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>positive_review_logits</th>\n",
       "      <th>positive_review_probability</th>\n",
       "      <th>reviews</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1.511887</td>\n",
       "      <td>0.819341</td>\n",
       "      <td>This was very well done.</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   positive_review_logits  positive_review_probability  \\\n",
       "0                1.511887                     0.819341   \n",
       "\n",
       "                    reviews  \n",
       "0  This was very well done.  "
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%bigquery\n",
    "SELECT * FROM ML.PREDICT(MODEL mlpatterns.imdb_sentiment,\n",
    "  (SELECT 'This was very well done.' AS reviews)\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, do it at scale, on consumer complaints about financial products and services:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bigquery preds\n",
    "SELECT * FROM ML.PREDICT(MODEL mlpatterns.imdb_sentiment,\n",
    "  (SELECT consumer_complaint_narrative AS reviews \n",
    "   FROM `bigquery-public-data`.cfpb_complaints.complaint_database\n",
    "   WHERE consumer_complaint_narrative IS NOT NULL\n",
    "   )\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>positive_review_logits</th>\n",
       "      <th>positive_review_probability</th>\n",
       "      <th>reviews</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>-3.725246</td>\n",
       "      <td>0.023540</td>\n",
       "      <td>ADP TotalPay card with money network upgraded ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>-0.889956</td>\n",
       "      <td>0.291119</td>\n",
       "      <td>I paid off my Pay Pal Credit in full except fo...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>-6.391967</td>\n",
       "      <td>0.001672</td>\n",
       "      <td>Well, I called citi on XXXX/XXXX/16 to determi...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   positive_review_logits  positive_review_probability  \\\n",
       "0               -3.725246                     0.023540   \n",
       "1               -0.889956                     0.291119   \n",
       "2               -6.391967                     0.001672   \n",
       "\n",
       "                                             reviews  \n",
       "0  ADP TotalPay card with money network upgraded ...  \n",
       "1  I paid off my Pay Pal Credit in full except fo...  \n",
       "2  Well, I called citi on XXXX/XXXX/16 to determi...  "
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "preds[:3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'I get phone calls morning XXXX  and night. I have told them to stop so many calls but they still call even on Sunday in the morning. I had two calls in a row on a Sunday morning from XXXX XXXX. I received 9 calls on Saturday. I receive about 9 during the week day every day as well.'"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# what's does a \"positive\" complaint look like?\n",
    "preds.sort_values(by='positive_review_probability', ascending=False).iloc[1]['reviews']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'I have noticed inconsistencies with the information all three credit bureaus have. As you know, this is not allowed under my rights and also a clear indication that this information was NOT properly verified upon you receiving it. XXXX has a Chapter XXXX Bankruptcy, REF # XXXX as Date Filed : XX/XX/XXXX, however XXXX   has the following info claiming to be accurate, Chapter XXXX Bankruptcy, REF # XXXX as Date Opened : XX/XX/XXXX, and Equifax is NOT reporting this information AT ALL!!! Also XXXX has XXXX XXXX, XXXX # XXXX Balance of {$3500.00} as Date Opened : XX/XX/XXXX, however XXXX has the following info claiming to be accurate, Balance of {$3500.00} as Date Opened : XX/XX/XXXX, and Equifax has the following info claiming to be accurate, Balance of {$3500.00} as Date Opened : XX/XX/XXXX. If these are the same accounts, how is the supposed verified information listed on my credit profiles different from one another? This is not possible and because of this inconsistency, please delete the following account from my credit profile immediately. I also asked if they would update my personal information in their system, they have not done so.'"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# what's does a \"typical\" complaint look like?\n",
    "preds.sort_values(by='positive_review_probability', ascending=False).iloc[len(preds)//2]['reviews']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Copyright 2020 Google Inc. Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
